package com.liuyi.pay.ali;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.alipay.AliPayApiConfigKit;
import com.ijpay.core.kit.QrCodeKit;
import com.liuyi.tools.web.unusual.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;


/**
 * 阿里支付服务类
 */
@Slf4j
@Service
public class AliPayService {

    @Resource
    private AliPayBeans aliPayBeans;

    /**
     * 回调验证
     */
    public Dict notify(String appId, HttpServletRequest request) {
        AliPayApiConfigKit.setThreadLocalAppId(appId);
        AliPayBean aliPayBean = aliPayBeans.get(appId);
        // 获取支付宝POST过来反馈信息
        Map<String, String> params = AliPayApi.toMap(request);
        try {
            boolean verifyResult = AlipaySignature.rsaCheckV1(params, aliPayBean.getPublicKey(), "UTF-8", "RSA2");
            if (verifyResult) {
                Map<String, Object> result = new HashMap<>();
                result.putAll(params);
                return new Dict(result);
            }
        } catch (AlipayApiException e) {
            log.error("支付回调：" + e.getErrCode() + " msg:" + e.getErrMsg());
        }
        throw new BizException("回调验证失败");
    }

    /**
     * 获取回调订单号
     */
    public String getOrderNo(HttpServletRequest request) {
        return AliPayApi.toMap(request).get("out_trade_no");
    }

    /**
     * 交易查询
     */
    public String tradeQuery(String appid, String orderNo) {
        return tradeQuery(appid, orderNo, null);
    }

    /**
     * 交易查询
     */
    public String tradeQuery(String appid, String orderNo, String tradeNo) {
        AliPayApiConfigKit.setThreadLocalAppId(appid);
        try {
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            if (StrUtil.isNotEmpty(orderNo)) {
                model.setOutTradeNo(orderNo);
            }
            if (StrUtil.isNotEmpty(tradeNo)) {
                model.setTradeNo(tradeNo);
            }
            return AliPayApi.tradeQueryToResponse(model).getBody();
        } catch (AlipayApiException e) {
            log.error("支付宝查询交易失败：" + e.getErrCode() + " 信息：" + e.getErrMsg(), e);
            throw new BizException("查询失败");
        }
    }

    /**
     * 退款
     */
    public String tradeRefund(String appid, String orderNo, BigDecimal refundAmount, String refundReason) {
        AliPayApiConfigKit.setThreadLocalAppId(appid);
        try {
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            if (StrUtil.isNotEmpty(orderNo)) {
                model.setOutTradeNo(orderNo);
            }
            model.setRefundAmount(refundAmount.toString());
            model.setRefundReason(refundReason);
            return AliPayApi.tradeRefundToResponse(model).getBody();
        } catch (AlipayApiException e) {
            log.error("支付宝退款失败：" + e.getErrCode() + " 信息：" + e.getErrMsg(), e);
            throw new BizException("退款失败");
        }
    }

    /**
     * PC支付
     * <p>
     * 支付成功直接返回二维码了
     * </p>
     */
    public void pcPay(String appid, String orderNo, BigDecimal totalAmount, String subject, String body, String passback_params, String notify_url, HttpServletResponse response) {
        AliPayApiConfigKit.setThreadLocalAppId(appid);
        AliPayBean aliPayBean = aliPayBeans.get(appid);
        try {
            String notifyUrl = aliPayBean.getDomain() + notify_url;
            AlipayTradePagePayModel model = new AlipayTradePagePayModel();
            model.setOutTradeNo(orderNo);
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
            model.setTotalAmount(totalAmount.toString());
            model.setSubject(subject);
            model.setBody(body);
            model.setPassbackParams(passback_params);
            AliPayApi.tradePage(response, model, notifyUrl, null);
        } catch (Exception e) {
            log.error("支付宝PC支付失败：" + e.getMessage(), e);
            throw new BizException("支付宝支付失败");
        }
    }

    /**
     * 扫码支付
     */
    public void tradePreCreatePay(String appid, String orderNo, BigDecimal totalAmount, String subject, String timeoutExpress, String notify_url, HttpServletResponse response) {
        AliPayApiConfigKit.setThreadLocalAppId(appid);
        AliPayBean aliPayBean = aliPayBeans.get(appid);
        String notifyUrl = aliPayBean.getDomain() + notify_url;
        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setSubject(subject);
        model.setTotalAmount(totalAmount.toString());
        model.setTimeoutExpress(timeoutExpress);
        model.setOutTradeNo(orderNo);
        try {
            String resultStr = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl).getBody();
            JSONObject jsonObject = JSONObject.parseObject(resultStr);
            QrCodeKit.encodeOutPutSteam(response.getOutputStream(), jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code"), BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, "png", 200, 200);
        } catch (Exception e) {
            log.error("支付宝扫码支付失败：" + e.getMessage(), e);
            throw new BizException("支付宝支付失败");
        }
    }
}
